#include "PresetEditWindow.h"

#include "server/DmxClient.h"
#include "MainWindow.h"
#include "OutputWindow.h" /* for DmxChannel */

	
PresetEditWindow::PresetEditWindow(LightingPreset *preset)
	: QWidget()
	, m_preset(preset)
	, m_lockValueChanged(false)
	, m_showChangesLive(false)
{
	setWindowTitle(tr("Preset \"%1\" - DMX Lighting Control").arg(preset->name()));
	setWindowIcon(QIcon("/usr/share/icons/Bluecurve/32x32/apps/icon-mixer.png"));
	
	setupGui();
}

void PresetEditWindow::setupGui()
{
	QVBoxLayout *vbox = new QVBoxLayout(this);
	
	// Top area to edit name
	QHBoxLayout *nameHBox = new QHBoxLayout();
	nameHBox->addWidget(new QLabel("Name: "));
	
	QLineEdit *nameEdit = new QLineEdit(m_preset->name());
	connect(nameEdit, SIGNAL(textChanged(QString)), this, SLOT(nameChanged(QString)));
	nameHBox->addWidget(nameEdit);
	
	nameHBox->addWidget(new QLabel("Num: "));
	
	QSpinBox *spin = new QSpinBox();
	spin->setMinimum(0);
	spin->setMaximum(255);
	spin->setValue(m_preset->num());
	connect(spin, SIGNAL(valueChanged(int)), this, SIGNAL(presetNumChanged(int)));
	connect(m_preset, SIGNAL(numChanged(int)), spin, SLOT(setValue(int)));
	nameHBox->addWidget(spin);
	
	nameHBox->addStretch(1);
	
	vbox->addLayout(nameHBox);
	
	// Placeholder for the sliders
	m_sliderGrid = new QGridLayout();
	vbox->addLayout(m_sliderGrid);
	
	
	QHBoxLayout *lowerHBox = new QHBoxLayout();
	
	m_showIgnored = new QCheckBox("Show Ignored");
	m_showIgnored->setChecked(false);
	connect(m_showIgnored, SIGNAL(toggled(bool)), this, SLOT(generateSliderUI()));
	lowerHBox->addWidget(m_showIgnored);
	
	QCheckBox *checkbox = new QCheckBox("Show Changes Live on Outputs");
	checkbox->setChecked(false);
	connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(showChangesLive(bool)));
	lowerHBox->addWidget(checkbox);
	
	lowerHBox->addStretch(1);
	
	vbox->addLayout(lowerHBox);
	
	
	// Generate initial slider UI - will regenerate after changing channel indexes 
	generateSliderUI();
	
	
}
	
void PresetEditWindow::generateSliderUI()
{
	// Clear the slider grid of old controls
	while(m_sliderGrid->count() > 0)
	{
		QLayoutItem *item = m_sliderGrid->itemAt(m_sliderGrid->count() - 1);
		m_sliderGrid->removeItem(item);
		if(QWidget *widget = item->widget())
		{
			// disconnect any slots
			disconnect(widget, 0, this, 0);
			
			m_sliderGrid->removeWidget(widget);
			delete widget;
		}
			
		delete item;
		item = 0;
	}
	
	QWidget *parent = this;
	
	QGridLayout *lay = m_sliderGrid;
	
	// Rebuild UI
	QCheckBox *checkbox; // hold and enabled
	QSlider *slider; // value
	QSpinBox *spin; // value and channel
	QLabel *label;
	
	QSettings settings;
	
	QList<QWidget*> wHold;
	QList<QWidget*> wValues;
	QList<QWidget*> wSliders;
	
	bool showIgnored = m_showIgnored->isChecked();
	
	int row = 0;
	int col = 0;
	
	int counter = 0;
	
	PresetValueList values = m_preset->values();
	
	int x=0;
	foreach(PresetValue *pv, values)
		pv->setIdx(x++);
	
	// Sort values by channel()->num()
	qSort(values.begin(), values.end(), PresetValue::comparitor);
	
	foreach(PresetValue *pv, values)
	{
		DmxChannel *chan = pv->channel();
		
		row = 0;
		
		// Start a new widget hash
		WidgetHash widgets;
		
		if(pv->ignore() && !showIgnored)
		{
			pv->setWidgets(widgets);
			continue;
		}
		
		checkbox = new QCheckBox("Ignore");
		checkbox->setProperty("num",pv->idx());
		checkbox->setChecked(pv->ignore());
		connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(ignoreChanged(bool)));
		lay->addWidget(checkbox, row++, col);
		wHold << checkbox;
		//widgets["hold"] = checkbox;
		
		spin = new QSpinBox();
		spin->setMinimum(0);
		spin->setMaximum(255);
		spin->setValue(pv->value());
		lay->addWidget(spin, row++, col);
		wValues << spin;
		widgets["spin"] = spin;
		
		slider = new QSlider(Qt::Vertical, parent);
		slider->setMinimum(0);
		slider->setMaximum(255);
		slider->setValue(pv->value());
		slider->setProperty("num",pv->idx());
		connect(slider, SIGNAL(valueChanged(int)), parent, SLOT(sliderValueChanged(int)));
		connect(spin, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int)));
		connect(slider, SIGNAL(valueChanged(int)), spin, SLOT(setValue(int)));
		wSliders << slider;
		lay->addWidget(slider, row++, col, Qt::AlignHCenter);
		widgets["value"] = slider;
		

		label = new QLabel(QString("Chan #%1").arg(chan->num()));
		lay->addWidget(label, row++, col);
		widgets["chan"] = label;
		
		label = new QLabel(QString("DMX #%1").arg(chan->dmxNum()));
		lay->addWidget(label, row++, col);
		widgets["dmx"] = label;
			
		label = new QLabel(QString("<b>%1</b>").arg(chan->name()));
		lay->addWidget(label, row++, col);
		widgets["name"] = label;
		
		// Store UI element pointers for updates later
		pv->setWidgets(widgets);
		
		updateIgnoreUi(pv);
		
		col++;
		counter++;
	}
	
	lay->addItem(new QSpacerItem(1,1,QSizePolicy::Expanding),1,col++);
	
	QWidget *lw = 0;
	QList<QWidget*> allWidgets  = QList<QWidget*>() 
		<< wHold
		<< wValues
		<< wSliders;
	
	foreach(QWidget *w, allWidgets)
	{
		if(lw)
			QWidget::setTabOrder(lw,w);
		lw = w;
	}
	
	adjustSize();
}

#define GetChannelFromSender() \
	QObject *senderObject = sender(); \
	int channelNum = senderObject ? senderObject->property("num").toInt() : -1; \
	if(channelNum < 0) \
	{ \
		qDebug() << "Error reading slider number, nothing changed."; \
		return; \
	} \
	if(channelNum < 0 || channelNum >= m_preset->values().size()) \
	{ \
		qDebug() << "Slider number out of range.";\
		return; \
	} \
	PresetValue *pv = m_preset->values().at(channelNum);
	

void PresetEditWindow::sliderValueChanged(int value)
{
	GetChannelFromSender();
	//chan->setValue(value);
	pv->setValue(value);
	qDebug() << "PresetEditWindow::sliderValueChanged: pv dmx num:"<<pv->channel()->dmxNum()<<", new value:"<<value;
	
	// For the purpose of showing changes live, assume we are at 100% for this preset
	if(m_showChangesLive)
		pv->channel()->setValue( value );
}

void PresetEditWindow::showChangesLive(bool flag)
{
	m_showChangesLive = flag;
	
	// For the purpose of showing changes live, assume we are at 100% for this preset
	if(flag)
		foreach(PresetValue *pv, m_preset->values())
			pv->channel()->setValue( pv->value() );
}

void PresetEditWindow::nameChanged(QString name)
{
	m_preset->setName(name);
	emit presetNameChanged(name);
	setWindowTitle(tr("Preset \"%1\" - DMX Lighting Control").arg(name));
}


void PresetEditWindow::ignoreChanged(bool flag)
{
	GetChannelFromSender();
	//chan->setIsEnabled(flag);
	pv->setIgnore(flag);
	
	updateIgnoreUi(pv);
	
	if(!m_showIgnored->isChecked() && !flag)
		QTimer::singleShot(0, this, SLOT(generateSliderUI()));
}

void PresetEditWindow::updateIgnoreUi(PresetValue *pv)
{
	WidgetHash widgets = pv->widgets();
	bool flag = pv->ignore();
	
	foreach(QWidget *widget, widgets.values())
		widget->setEnabled(!flag);
}
